<template>
    <div>
        <Card v-show="isAdvanced" :bordered="false" :padding="0" style="width:100%;">
            <Table stripe border highlight-row :columns="resColumns" :data="pageData" @on-current-change="onResChange" :no-data-text="$t('goman.general.noData')" :no-filtered-data-text="$t('goman.general.noFilterData')"></Table>
            <div style="margin-top:15px;text-align:right">
                <Page class="myPage" :total="resList.length" :current="1" :page-size="pageSize" :page-size-opts="[5,10,20,30,40,50]" @on-change="onPageChange" @on-page-size-change="onPageSizeChange" placement="top" show-total show-sizer>
                </Page>
            </div>
            <div>&nbsp;</div>
        </Card>
        <Card style="width:100%;">
            <div slot="title">{{$t('goman.req.pre.title')}}</div>
            <div slot="extra" v-html="status"></div>
            <div>
                <Tabs v-show="res" :animated="false" v-model="resMode">
                    <Tab-pane label="Body">
                        <RadioGroup v-model="bodyMode" type="button" size="large">
                            <Radio label="pretty">{{$t('goman.req.pre.body.pretty')}}</Radio>
                            <Radio label="raw">{{$t('goman.req.pre.body.raw')}}</Radio>
                        </RadioGroup>
                        <span>&nbsp;&nbsp;&nbsp;&nbsp;{{$t('goman.req.pre.body.language')}}：{{ bodyLanguage }}</span>
                        <pre v-show="bodyMode==='raw'">{{ bodyRaw }}</pre>
                        <pre v-show="bodyMode==='pretty'" v-html="body"></pre>
                    </Tab-pane>
                    <Tab-pane label="Headers">
                        <Table stripe border :columns="headerColumns" :data="headers" :no-data-text="$t('goman.general.noData')" :no-filtered-data-text="$t('goman.general.noFilterData')"></Table>
                    </Tab-pane>
                    <Tab-pane label="Cookies">
                        <Table stripe border :columns="cookieColumns" :data="cookies" :no-data-text="$t('goman.general.noData')" :no-filtered-data-text="$t('goman.general.noFilterData')"></Table>
                    </Tab-pane>
                    <Tab-pane :label="$t('goman.req.pre.code')">
                        <pre>{{ code }}</pre>
                    </Tab-pane>
                    <Tab-pane :label="$t('goman.req.pre.report')">
                        <Table stripe border :columns="reportDurationColumns" :data="durations" :no-data-text="$t('goman.general.noData')" :no-filtered-data-text="$t('goman.general.noFilterData')"></Table>
                    </Tab-pane>
                </Tabs>
            </div>
        </Card>
    </div>
</template>

<style>
.hljs-ul {
  list-style: decimal;
  background-color: #fff;
  margin: 0px 0px 0 40px !important;
  padding: 0px;
}

.hljs-ul li {
  list-style: decimal-leading-zero;
  border-left: 1px solid #ddd !important;
  background: #fff;
  padding: 5px !important;
  margin: 0 !important;
  line-height: 14px;
  word-break: break-all;
  word-wrap: break-word;
}

.hljs-ul li:nth-of-type(even) {
  background-color: #f8f8f9;
  color: inherit;
}
</style>

<script lang="ts">
import { Vue, Component, Prop, Watch } from "vue-property-decorator";
import { CreateElement } from "vue/types/vue";
import _ from "lodash";
import hljs from "highlight.js";

@Component
export default class Pre extends Vue {
  @Prop() isAdvanced: boolean;
  @Prop() resList: Req.ResponseModel[];

  res: Req.ResponseModel | null = null;
  pageData: Req.ResponseModel[] = [];
  pageSize = 5;
  pageCount = 0;

  resColumns = <any[]>[
    {
      type: "index",
      width: 60,
      align: "center"
    },
    {
      title: "",
      key: "error"
    },
    {
      title: "",
      key: "contentLength",
      sortable: true
    },
    {
      title: "",
      render: (h: CreateElement, p: any) => {
        return h("span", p.row.duration.finish);
      }
    }
  ];
  headerColumns = <any[]>[
    {
      title: "",
      key: "key"
    },
    {
      title: "",
      key: "value"
    }
  ];
  cookieColumns = <any[]>[
    {
      title: "",
      key: "Name"
    },
    {
      title: "",
      key: "Value"
    },
    {
      title: "",
      key: "Path"
    },
    {
      title: "",
      key: "Domain"
    },
    {
      title: "",
      key: "Expires"
    }
  ];
  reportDurationColumns = <any[]>[
    {
      title: "",
      key: "dns"
    },
    {
      title: "",
      key: "conn"
    },
    {
      title: "",
      key: "req"
    },
    {
      title: "",
      key: "delay"
    },
    {
      title: "",
      key: "res"
    },
    {
      title: "",
      key: "finish"
    }
  ];

  bodyMode: "pretty" | "raw" = "pretty";
  bodyLanguage: string = "";
  isPretty: boolean = true;
  isRaw: boolean = false;

  resMode: number = 0;

  created() {
    this.onLocale();
  }

  @Watch("$i18n.locale")
  onLocale() {
    this.resColumns[1].title = this.$t("goman.req.pre.listTable.hasError");
    this.resColumns[2].title = this.$t("goman.req.pre.listTable.contentLength");
    this.resColumns[3].title = this.$t("goman.req.pre.listTable.duration");

    this.headerColumns[0].title = this.$t("goman.list.key");
    this.headerColumns[1].title = this.$t("goman.list.value");

    this.cookieColumns[0].title = this.$t("goman.req.pre.cookie.name");
    this.cookieColumns[1].title = this.$t("goman.req.pre.cookie.value");
    this.cookieColumns[2].title = this.$t("goman.req.pre.cookie.path");
    this.cookieColumns[3].title = this.$t("goman.req.pre.cookie.domain");
    this.cookieColumns[4].title = this.$t("goman.req.pre.cookie.expires");

    this.reportDurationColumns[0].title = this.$t("goman.req.report.table.dns");
    this.reportDurationColumns[1].title = this.$t(
      "goman.req.report.table.conn"
    );
    this.reportDurationColumns[2].title = this.$t("goman.req.report.table.req");
    this.reportDurationColumns[3].title = this.$t(
      "goman.req.report.table.delay"
    );
    this.reportDurationColumns[4].title = this.$t("goman.req.report.table.res");
    this.reportDurationColumns[5].title = this.$t(
      "goman.req.report.table.finish"
    );
  }

  mounted() {
    this.onResListChange();
  }

  onResChange(res: Req.ResponseModel, oldRes: Req.ResponseModel) {
    this.res = res;
  }

  @Watch("resList")
  onResListChange() {
    if (this.resList.length == 0) {
      this.bodyMode = "pretty";
      this.resMode = 0;
      return;
    }

    this.onPageSizeChange(this.pageSize);
  }

  onPageChange(pi: number) {
    if (pi > this.pageCount) {
      return;
    }

    this.pageData = [];

    let i = (pi - 1) * this.pageSize;

    for (let j = 0; j < this.pageSize; j++) {
      let k = i + j;
      if (k >= this.resList.length) {
        break;
      }

      this.pageData.push(this.resList[k]);
    }

    this.pageData[0]["_highlight"] = true;
    this.onResChange(this.pageData[0], this.pageData[0]);
  }

  onPageSizeChange(ps: number) {
    this.pageSize = ps;
    this.pageCount = Math.ceil(this.resList.length / this.pageSize);
    this.onPageChange(1);
  }

  get status(): string {
    if (!this.res) {
      return "";
    }

    let status = `${this.$t(
      "goman.req.pre.proto"
    )}：<span style="color:#3399ff;">${this.res.proto}</span>`;
    status += `&nbsp;&nbsp;&nbsp;&nbsp;${this.$t(
      "goman.req.pre.status"
    )}：<span style="color:#3399ff;">${this.res.status}</span>`;
    status += `&nbsp;&nbsp;&nbsp;&nbsp;${this.$t(
      "goman.req.report.table.finish"
    )}：<span style="color:#3399ff;">${this.res.duration.finish}</span>`;

    return status;
  }

  get bodyRaw(): string {
    if (!this.res || !this.res.body) {
      return "";
    }

    return this.res.body;
  }

  get body(): string {
    if (!this.res || !this.res.body) {
      return "";
    }

    let body = this.res.body;
    let contentType = "text/plain";

    _.forEach(this.res.headers, (v, k) => {
      k = k.toLowerCase();
      if (k == "content-type") {
        contentType = v[0];
      }
      return;
    });

    let language: string[] | undefined = undefined;
    if (contentType.indexOf("application/json") != -1) {
      body = JSON.stringify(JSON.parse(body), undefined, 4);
      language = ["json"];
    } else if (contentType.indexOf("application/xml") != -1) {
      language = ["xml"];
    } else if (contentType.indexOf("text/html") != -1) {
      language = ["html"];
    }

    let pretty = hljs.highlightAuto(body, language);
    this.bodyLanguage = pretty.language;
    if (!language) {
      this.bodyLanguage += "(auto)";
    }
    body =
      '<ul class="hljs-ul"><li>' +
      _.replace(pretty.value, /\n/g, "\n</li><li>") +
      "</li></ul>";

    return body;
  }

  get headers(): Req.HeaderModel[] {
    if (!this.res) {
      return [];
    }

    let headers: Req.HeaderModel[] = [];

    _.forIn(this.res.headers, (va, k) => {
      // headers += k + '：' + _.join(v, ';') + '\r\n'
      _.forEach(va, v => {
        headers.push({
          key: k,
          value: v
        });
      });
    });

    return headers;
  }

  get cookies(): Req.CookieModel[] {
    return this.res ? this.res.cookies : [];

    // if (!this.res) {
    //     return ''
    // }

    // let cookies: string = ''

    // _.forEach(this.res.Cookies, (v) => {
    //     cookies += JSON.stringify(v) + '\r\n'
    // })

    // return cookies
  }

  get durations(): Req.ResponseDuration[] {
    let durations: Req.ResponseDuration[] = [];

    if (this.res) {
      durations.push(this.res.duration);
    }

    return durations;
  }

  get code(): string {
    return this.res ? this.res.code + "[body ignore]" : "";
  }
}
</script>
